module basediv(
  input clk,
  input rst,
  
  input valid_i,
  input flush,

  input divw,
  input div_signed,
  input [63:0] src1,
  input [63:0] src2,
  
  output reg ready,
  output reg valid_o,
  output [63:0] quotient,
  output [63:0] remainder
);
  reg [127:0] rem;
  reg [63:0] quo;
  reg [127:0] divisor;
  reg [6:0] cnt;
  reg quo_sign,rem_sign;
  reg res_w;
  wire src1_sign = div_signed&(divw?src1[31]:src1[63]);
  wire src2_sign = div_signed&(divw?src2[31]:src2[63]);
  
  always @(posedge clk) begin
    if(rst|flush) begin
      quo <= 64'b0;
      rem <= 128'b0;
      divisor <= 128'b0;
      cnt <= 7'b0;
      quo_sign <= 1'b0;
      rem_sign <= 1'b0;
      valid_o <= 1'b0;
      ready <= 1'b1;
      res_w <= 1'b0;
    end else begin
      quo <= 64'b0;
      rem <= 128'b0;
      valid_o <= 1'b0;
      if(valid_i&ready) begin
        ready <= 1'b0;
        quo <= 64'b0;
        res_w <= divw;
        if(divw) begin
          if(div_signed&src1[31]) rem  <= {96'b0,{(~src1[31:0])+32'b1}}; 
          else rem <= {96'b0,src1[31:0]}; 
          if(div_signed&src2[31]) divisor  <= {33'b0,32'b0,{(~src2[31:0])+32'b1},31'b0}; 
          else divisor <= {33'b0,32'b0,src2[31:0],31'b0};
          cnt <= 7'd32;
        end else begin
          if(div_signed&src1[63]) rem  <= {64'b0,(~src1)+64'b1}; 
          else rem <= {64'b0,src1}; 
          if(div_signed&src2[63]) divisor  <= {1'b0,{(~src2)+64'b1},63'b0}; 
          else divisor <= {1'b0,src2,63'b0}; 
          cnt <= 7'd64;
        end
        if(src1_sign != src2_sign) quo_sign <= 1'b1;
        else quo_sign <= 1'b0;
        rem_sign <= src1_sign;
      end else if(ready == 1'b0) begin
        quo[63:1] <= quo[62:0];
        if(rem >= divisor) begin
          rem <= rem - divisor;
          quo[0] <= 1'b1;
        end else begin
          rem <= rem;
          quo[0] <= 1'b0;
        end
        divisor <= divisor >> 1;
        cnt <= cnt - 7'd1;
        if(cnt == 7'd1) begin
          ready <= 1'b1;
          valid_o <= 1'b1;
        end
      end
    end
  end
  wire [63:0] quotient_out = quo_sign?((~quo)+64'b1):quo;
  wire [63:0] remainder_out = rem_sign?((~rem[63:0])+64'b1):rem[63:0];
  assign quotient[31:0] = quotient_out[31:0];
  assign quotient[63:32] = res_w?{32{quotient_out[31]}}:quotient_out[63:32];
  assign remainder[31:0] = remainder_out[31:0];
  assign remainder[63:32] = res_w?{32{remainder_out[31]}}:remainder_out[63:32];
endmodule
